﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace MySearch
{
    public enum KpmgRepeaterAction { None, Sort }

    public enum KpmgRepeaterColumnType { Check, HtmlData }

    public enum SortDirection { Asc, Desc }

    public enum SortType { Str, Date }

    public class KpmgRepeaterColumnDef
    {
        public KpmgRepeaterColumnType ColumnType { get; private set; }
        public string Title { get; private set; }
        public string Key { get; private set; }
        public int Width { get; private set; }
        public bool CanSort { get; private set; }
        public SortType SType { get; private set; }

        public KpmgRepeaterColumnDef(KpmgRepeaterColumnType colType, string title, string key, int width, bool canSort, SortType SType = SortType.Str)
        {
            this.ColumnType = colType;
            this.Title = title;
            this.Key = key;
            this.Width = width;
            this.CanSort = canSort;
            this.SType = SType;
        }

        public static KpmgRepeaterColumnDef CreateColumnCheck()
        {
            return new KpmgRepeaterColumnDef(KpmgRepeaterColumnType.Check, "<input type=\"Checkbox\" id=\"cbAll\">", "", 20, false);
        }

        public static KpmgRepeaterColumnDef CreateColumnData(string title, string key, int width, bool canSort, SortType SType = SortType.Str)
        {
            return new KpmgRepeaterColumnDef(KpmgRepeaterColumnType.HtmlData, title, key, width, canSort, SType);
        }
    }

    public class KpmgRepeaterColumnData
    {
        public string Value { get; private set; }
        public string SortValue { get; private set; }

        public KpmgRepeaterColumnData(string val, string sortVal)
        {
            this.Value = val;
            this.SortValue = sortVal;
        }
    }

    public delegate void ExcuteCommand(KpmgRepeaterAction act, string arg);

    public class KpmgRepeater
    {
        public ExcuteCommand ItemCommand;

        private IList<KpmgRepeaterColumnDef> _Columns;
        private IList<IDictionary<string, KpmgRepeaterColumnData>> _RepeaterData;
        private string _SortKey;
        private bool _SortInAsc;
        private IDictionary<string, string> _dicInfo;

        #region properties
        public IList<KpmgRepeaterColumnDef> Columns { get { return this._Columns; } }
        public IList<IDictionary<string, KpmgRepeaterColumnData>> RepeaterData { get { return this._RepeaterData; } }
        public string SortKey { get { return this._SortKey; } }
        public bool SortInAsc { get { return this._SortInAsc; } }
        public IDictionary<string, string> DicInfo { get { return this._dicInfo; } }
        #endregion

        public KpmgRepeater(IList<KpmgRepeaterColumnDef> cols, IList<IDictionary<string, KpmgRepeaterColumnData>> data,
            string sortKey, bool isAsc, IDictionary<string, string> dic, SortType sortType = SortType.Str)
        {
            if (cols == null || cols.Count == 0)
                throw new Exception("Invalid column definition");

            if (data == null)
                throw new Exception("Invalid data");

            if (cols.Where(x => x.Key == sortKey).Count() == 0)
                throw new Exception("Invalid sort column");

            if (sortType == SortType.Date)
            {
                if (isAsc)
                    this._RepeaterData = data.OrderBy(x => x[sortKey].SortValue).ToList();
                else
                    this._RepeaterData = data.OrderByDescending(x => x[sortKey].SortValue).ToList();
            }
            else
            {
                if (isAsc)
                    this._RepeaterData = data.OrderBy(x => x[sortKey].SortValue).ToList();
                else
                    this._RepeaterData = data.OrderByDescending(x => x[sortKey].SortValue).ToList();
            }

            this._SortKey = sortKey;
            this._SortInAsc = isAsc;
            this._Columns = cols;
            this._dicInfo = dic;
        }

        public ITemplate GetTemplate(ListItemType itemType)
        {
            ITemplate tmpl;

            switch (itemType)
            {
                case ListItemType.Header:
                    tmpl = new HeaderTemplate(this, _dicInfo);
                    break;

                case ListItemType.Item:
                case ListItemType.AlternatingItem:
                    tmpl = new DataRowTemplate(this);
                    break;

                case ListItemType.Footer:
                    tmpl = new FooterTemplate(this);
                    break;

                default:
                    throw new Exception("Not implemented");
            }

            return tmpl;
        }

        public void List_ItemDataBound(object source, RepeaterItemEventArgs e) { }

        public void List_ItemCommand(object source, RepeaterCommandEventArgs e)
        {
            KpmgRepeaterAction act;
            if (!Enum.TryParse<KpmgRepeaterAction>(e.CommandName, true, out act))
                return;

            ItemCommand(act, e.CommandArgument.ToString());
        }
    }

    #region internal template class
    internal class HeaderTemplate : ITemplate
    {
        private KpmgRepeater _Repeater;
        private IDictionary<string, string> _dicOtherInfo;

        public HeaderTemplate(KpmgRepeater rpt)
        {
            this._Repeater = rpt;
        }

        public HeaderTemplate(KpmgRepeater rpt, IDictionary<string, string> dic)
        {
            this._Repeater = rpt;
            this._dicOtherInfo = dic;
        }

        public void InstantiateIn(Control container)
        {
            //Table start tag
            container.Controls.Add(new LiteralControl("<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">"));

            //Table row start tag
            container.Controls.Add(new LiteralControl("<tr class=\"repeaterHeader\">"));

            bool isFirtCol = true;
            string leftBorderStyle = " style='border-left: 1px solid #CAE2FA'";
            string appendStyle = "";
            foreach (KpmgRepeaterColumnDef col in this._Repeater.Columns)
            {
                if (isFirtCol)
                    appendStyle = leftBorderStyle;
                else
                    appendStyle = "";
                if (col.CanSort)
                {
                    string strDiret = "Desc";
                    if (col.Key == this._Repeater.SortKey && !this._Repeater.SortInAsc)
                        strDiret = "Asc";

                    container.Controls.Add(new LiteralControl("<td" + appendStyle + " class=\"RepeaterTableHead\" width=\"" + col.Width + "%\">"));

                    LinkButton lb = new LinkButton();
                    lb.ID = col.Key;
                    lb.Text = col.Title;
                    lb.CommandName = KpmgRepeaterAction.Sort.ToString();
                    lb.CommandArgument = col.Key + "," + strDiret + "," + col.SType.ToString();
                    container.Controls.Add(lb);

                    if (col.Key == this._Repeater.SortKey)
                    {

                        string strImge = this._Repeater.SortInAsc ? _dicOtherInfo["AscImage"] : _dicOtherInfo["DescImage"];
                        container.Controls.Add(new LiteralControl("<img src=\"" + strImge + "\" style=\"padding-left:5px\" />"));
                    }

                    container.Controls.Add(new LiteralControl("</td>"));
                }
                else
                {
                    container.Controls.Add(new LiteralControl("<td" + appendStyle + " class=\"RepeaterTableHead\">" + col.Title + "</td>"));
                }
                isFirtCol = false;
            }

            //Table row end tag
            container.Controls.Add(new LiteralControl("</tr>"));
        }
    }

    internal class FooterTemplate : ITemplate
    {
        private KpmgRepeater _Repeater;

        public FooterTemplate(KpmgRepeater rpt)
        {
            this._Repeater = rpt;
        }

        public void InstantiateIn(Control container)
        {
            int colmuns = _Repeater.Columns.Count;
            string strEmpty = "<div style=\"margin: 0px auto;\"><p style=\"text-align: center\">The list is empty</p></div>";

            if (_Repeater.RepeaterData.Count == 0)
                container.Controls.Add(new LiteralControl("<tr><td class='TableRow' colspan=\"" + colmuns + "\" align=\"center\">" + strEmpty + "</td></tr>"));

            //one more row
            container.Controls.Add(new LiteralControl("<tr class=\"repeaterFooter\">"
                + "<td colspan=\"" + this._Repeater.Columns.Count.ToString() + "\" bgcolor=\"#E0ECF8\" height=\"8px\"></td>"
                + "</tr>"));

            //Table
            container.Controls.Add(new LiteralControl("</table>"));
        }
    }

    internal class DataRowTemplate : ITemplate
    {
        private KpmgRepeater _Repeater;
        private int _Cnt = 0;

        public DataRowTemplate(KpmgRepeater rpt)
        {
            this._Repeater = rpt;
        }

        public void InstantiateIn(Control container)
        {
            if (this._Repeater.RepeaterData.Count == 0 || this._Cnt == this._Repeater.RepeaterData.Count)
                return;

            IDictionary<string, KpmgRepeaterColumnData> dic = this._Repeater.RepeaterData[this._Cnt];

            //Get current data 
            container.Controls.Add(new LiteralControl("<tr>"));

            //Calculate style class
            string strClass = (this._Cnt % 2 == 0 ? "RepeaterTableRow" : "RepeaterTableRowAlternative");

            bool isFirtCol = true;
            string leftBorderStyle = " style='border-left: 1px solid #E9EDF8'";
            string appendStyle = "";
            foreach (KpmgRepeaterColumnDef col in this._Repeater.Columns)
            {
                if (isFirtCol)
                    appendStyle = leftBorderStyle;
                else
                    appendStyle = "";
                switch (col.ColumnType)
                {
                    case KpmgRepeaterColumnType.HtmlData:
                        container.Controls.Add(new LiteralControl("<td" + appendStyle + " class=\"" + strClass + "\">" + dic[col.Key].Value + "</td>"));
                        break;

                    case KpmgRepeaterColumnType.Check:
                        container.Controls.Add(new LiteralControl("<td" + appendStyle + " class=\"" + strClass + "\">"));

                        CheckBox cb = new CheckBox();
                        cb.ID = "cbSelect";
                        cb.Checked = false;
                        container.Controls.Add(cb);

                        container.Controls.Add(new LiteralControl("</td>"));

                        break;

                    default:
                        throw new Exception("Not implemented");
                }
                isFirtCol = false;
            }

            container.Controls.Add(new LiteralControl("</tr>"));

            this._Cnt++;
        }

    }
    #endregion
}
